hdu 5592 ZYB's Game 树状数组
ZYB's Game
Time Limit: 20 Sec
Memory Limit: 256 MB
题目连接
http://acm.hdu.edu.cn/showproblem.php?pid=5592
Description
ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to
restore the premutation.
Pair (i,j)(i<j) is considered as a reverse log if Ai>Aj is matched.
Input
In the first line there is the number of testcases T.
For each teatcase:
the first line there is one number N.
1≤T≤100000,1≤N≤10000000
Output
For each testcase,print the ans.
Sample Input
1
3
0 1 2
Sample Output
3 1 2
HINT
题意
题解:
很显然可以发现,a[i]-a[i-1],就表示在[1,i]中比i大的数有多少个
那么我们倒着做就好了,拿一个树状数组来维护就行了~
代码:
#include<iostream> #include<stdio.h> #include<cstring> using namespace std; #define maxn 50005 long long a[maxn]; int ans[maxn]; #define lowbit(x) ((x)&(-x)) struct BinaryIndexTree { int val[maxn],sz; void init(int sz){ this->sz=sz; memset(val , 0 , sizeof(int)*(sz+5)); } void updata(int pos ,int key){ while(pos<=sz){ val[pos]+=key; pos+=lowbit(pos); } } long long prefixsum(int pos){ long long res=0; while(pos>0){ res+=val[pos]; pos-=lowbit(pos); } return res; } int query(int l,int r){ return prefixsum(r)-prefixsum(l-1); } //到第一个大于等于k的位置返回 //若不存在,返回-1 int lower_bound(long long k){ if(prefixsum(sz)<k) return -1; int l = 1 , r = sz; while(l <= r){ int mid = l + ((r-l)>>1); if(prefixsum(mid) < k) l = mid + 1; else r = mid - 1; } return l; } }solver; long long c[maxn]; int main() { int t;scanf("%d",&t); for(int cas=1;cas<=t;cas++) { memset(a,0,sizeof(a)); memset(c,0,sizeof(c)); int n;scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%I64d",&a[i]); for(int i=1;i<=n;i++) c[i]=a[i]-a[i-1]; solver.init(n); for(int i=1;i<=n;i++) solver.updata(i,1); int tmp = 0; for(int i=n;i>=1;i--) { ans[i]=solver.lower_bound(n-tmp-c[i]); solver.updata(ans[i],-1); tmp++; } for(int i=1;i<=n;i++) { if(i!=n) printf("%d ",ans[i]); else printf("%d\n",ans[i]); } } }